#pragma once
#include <memory>
#include <boost/signals2.hpp>
#include <boost/describe.hpp>
#include <SFML/Graphics/Color.hpp>
#include <nice2d/node.h>

enum HMode : int32_t {
    HMode_Left = 0,
    HMode_Center,
    HMode_Right,
    HMode_Max
};

BOOST_DESCRIBE_ENUM(HMode, HMode_Left, HMode_Center, HMode_Right,HMode_Max)

enum VMode : int32_t {
    VMode_Top = 0,
    VMode_Center,
    VMode_Bottom,
    VMode_Max
};

BOOST_DESCRIBE_ENUM(VMode, VMode_Top, VMode_Center, VMode_Bottom,VMode_Max)

enum Orientation {
    Orientation_H = 0,
    Orientation_V
};

BOOST_DESCRIBE_ENUM(Orientation, Orientation_H, Orientation_V)

class Entity : public Node
{
    friend class EntityMouseListener;
    friend class EntityData;
    DECLARE_OBJECT(Entity)
public:
    static sf::Vector2f adjustPosition(const sf::Vector2f &size,
                                       const sf::Vector2f &target, HMode h, VMode v, float xmargin = 3.0f, float ymargin = 3.0f);
    static sf::Vector2f adjustPosition(const sf::FloatRect &box,
                                       const sf::Vector2f &target, HMode h, VMode v, float xmargin = 3.0f, float ymargin = 3.0f);

    Entity(const sf::Vector2f &size = sf::Vector2f());
    virtual ~Entity();
public:
    void setSize(float width, float height);
    void setSize(const sf::Vector2f &size);
    sf::Vector2f getSize()const;
    boost::signals2::signal<void(const sf::Vector2f &)> sizeChanged;

    void setLeft(float left);
    void setTop(float top);
    void setRight(float right);
    void setBottom(float bottom);
    void setCenter(float x, float y);
    void setCenter(const sf::Vector2f &center);

    bool isUnderMouse();
    bool isContainPoint(const sf::Vector2f& point);
public:
    sf::FloatRect getBoundingBox()const;

    void setBackgroundColor(const sf::Color &color);
    void setBackground(BackgroundPointer background);
    sf::Color getBackgroundColor()const;

    void setZValue(uint32_t z);
    uint32_t getZValue()const;
public:
    void setOutline(const sf::Color &color, float thickness = 1.0f);
    float getOutlineThickness()const;
    void setCornerRadius(float radius, uint32_t count = 16);
public:
    virtual PTree serialize() override;
    virtual void deserialize(const PTree &node) override;
protected:
    void onUpdateNode(float deltaTime) override;
    virtual void onUpdateEntity(float deltaTime);

    void onDrawNode(sf::RenderTarget &target, sf::RenderStates states) const override;
    virtual void onDrawEntity(sf::RenderTarget &target, sf::RenderStates states)const;

    virtual void onMouseEnter();
    virtual void onMouseExit();
    virtual void onMousePressed(sf::Mouse::Button button);
    virtual void onMouseReleased(sf::Mouse::Button button);
    virtual void onMouseWheelScroll(float scroll);
    virtual void onMouseMoved(int x, int y);

    virtual void onSizeChanged();

    virtual void onBackgroundChanged();
private:
    std::unique_ptr<class EntityData> data;
};


